/*=============================================================================
ShaderComponents.cpp : FX Shaders semantic components implementation.
  Copyright (c) 2001 Crytek Studios. All Rights Reserved.

  Revision history:
    * Created by Honich Andrey

=============================================================================*/

#include "StdAfx.h"
#include "I3DEngine.h"
#include "CryHeaders.h"
#include "../Shadow_Renderer.h"

#if defined(WIN32) || defined(WIN64)
#include <direct.h>
#include <io.h>
#elif defined(LINUX)
#endif

static void sParseTexMatrix(const char *szScr, const char *szAnnotations, std::vector<STexSamplerFX>* pSamplers, SCGParam *vpp, int nComp, CShader *ef)
{
  uint32 i;
  const char *szSampler = gRenDev->m_cEF.mfParseFX_Parameter(szAnnotations, eType_STRING, "Sampler");
  assert (szSampler);
  if (szSampler)
  {
    for (i=0; i<pSamplers->size(); i++)
    {
      STexSamplerFX *sm = &(*pSamplers)[i];
      if (!stricmp(sm->m_szName.c_str(), szSampler))
      {
        vpp->m_nID = (UINT_PTR)sm->m_pTarget;
        break;
      }
    }
  }
}

static void sParseTimeExpr(const char *szScr, const char *szAnnotations, std::vector<STexSamplerFX>* pSamplers, SCGParam *vpp, int nComp, CShader *ef)
{
  if (szScr)
  {
    if (!vpp->m_pData)
      vpp->m_pData = new SParamData;
    char str[256];
    float f;
    int n = sscanf(szScr, "%s %f", str, &f);
    if (n == 2)
      vpp->m_pData->d.fData[nComp] = f;
    else
      vpp->m_pData->d.fData[nComp] = 1.0f;
  }
}

static void sParseGlobalShaderFlag(const char *szScr, const char *szAnnotations, std::vector<STexSamplerFX>* pSamplers, SCGParam *vpp, int nComp, CShader *ef)
{
  if (!ef)
    ef = gRenDev->m_RP.m_pShader;
  if (!ef)
    return;
  if (szScr)
  {
    if (!vpp->m_pData)
      vpp->m_pData = new SParamData;
    char str[256], strval[256];
    uint32 n = sscanf(szScr, "%s %s", str, strval);
    if (n == 2)
    {
      bool bOK = false;
      if (strval[0] == '%')
      {
        if (ef->m_pGenShader && ef->m_pGenShader->m_ShaderGenParams) 
        {
          SShaderGen *pGen = ef->m_pGenShader->m_ShaderGenParams;
          for (n=0; n<pGen->m_BitMask.Num(); n++)
          {
            SShaderGenBit *pBit = pGen->m_BitMask[n];
            if (!strcmp(pBit->m_ParamName.c_str(), strval))
            {
              vpp->m_pData->d.nData64[nComp] = pBit->m_Mask;
              break;
            }
          }
          if (n == pGen->m_BitMask.Num() && (gRenDev->m_cEF.m_nCombinationsProcess < 0))
          {
            iLog->Log("WARNING: Couldn't find global shader flag '%s' for shader '%s'", strval, ef->GetName());
            vpp->m_pData->d.nData64[nComp] = 0;
          }
        }
        else
          vpp->m_pData->d.nData64[nComp] = 0;
      }
      else
        vpp->m_pData->d.nData64[nComp] = shGetHex64(strval);
    }
    else
      vpp->m_pData->d.nData64[nComp] = 0;
  }
  else
  {
    assert(0);
  }
}

static void sParseRuntimeShaderFlag(const char *szScr, const char *szAnnotations, std::vector<STexSamplerFX>* pSamplers, SCGParam *vpp, int nComp, CShader *ef)
{
  if (szScr)
  {
    if (!vpp->m_pData)
      vpp->m_pData = new SParamData;
    char str[256], strval[256];
		str[0] = '\0'; strval[0] = '\0';
    uint32 n = sscanf(szScr, "%s %s", str, strval);
    if (n == 2)
    {
      bool bOK = false;
      if (strval[0] == '%')
      {
        SShaderGen *pGen = gRenDev->m_cEF.m_pGlobalExt;
        for (n=0; n<pGen->m_BitMask.Num(); n++)
        {
          SShaderGenBit *pBit = pGen->m_BitMask[n];
          if (!strcmp(pBit->m_ParamName.c_str(), strval))
          {
            vpp->m_pData->d.nData64[nComp] = pBit->m_Mask;
            break;
          }
        }
        if (n == pGen->m_BitMask.Num())
        {
          iLog->Log("Error: Couldn't find runtime shader flag '%s' for shader '%s'", strval, ef->GetName());
          vpp->m_pData->d.nData64[nComp] = 0;
        }
      }
      else
        vpp->m_pData->d.nData64[nComp] = shGetHex64(strval);
    }
    else
      vpp->m_pData->d.nData64[nComp] = 0;
  }
  else
  {
    assert(0);
  }
}

//======================================================================================

// GL = global
// PB = Per-Batch
// PI = Per-Instance
// SI = Per-Instance Static
// PF = Per-Frame
// PM = Per-Material
// SK = Skin data
// MP = Morph data

#define PARAM(a, b) #a, b
static SParamDB sParams[] = 
{  
  SParamDB(PARAM(SI_ObjMatrix, ECGP_Matr_SI_Obj), 0),  
  SParamDB(PARAM(SI_AmbientOpacity, ECGP_SI_AmbientOpacity), 0),
  SParamDB(PARAM(SI_ObjectAmbColComp, ECGP_SI_ObjectAmbColComp), 0),  
  SParamDB(PARAM(SI_BendInfo, ECGP_SI_BendInfo), 0),  

  SParamDB(PARAM(PI_ViewProjection, ECGP_Matr_PI_ViewProj), 0),
  SParamDB(PARAM(PF_ViewProjMatrix, ECGP_Matr_PF_ViewProjMatrix), 0),
	SParamDB(PARAM(PF_ViewProjMatrixPrev, ECGP_Matr_PF_ViewProjMatrixPrev), 0),
	SParamDB(PARAM(PB_ViewProjMatrixPrev, ECGP_Matr_PF_ViewProjMatrixPrev), 0),
  SParamDB(PARAM(PF_ViewProjZeroMatrix, ECGP_Matr_PF_ViewProjZeroMatrix), 0),
  SParamDB(PARAM(PB_ViewProjMatrix_IT, ECGP_Matr_PB_ViewProjMatrix_IT), 0),
  SParamDB(PARAM(PB_ViewProjMatrix_I, ECGP_Matr_PB_ViewProjMatrix_I), 0),

  SParamDB(PARAM(PB_View_IT, ECGP_Matr_PB_View_IT), 0),
  SParamDB(PARAM(PB_View_I, ECGP_Matr_PB_View_I), 0),
  SParamDB(PARAM(PB_View_T, ECGP_Matr_PB_View_T ), 0),
  SParamDB(PARAM(PB_View, ECGP_Matr_PB_View), 0),

  SParamDB(PARAM(PB_CameraMatrix_IT, ECGP_Matr_PB_Camera_IT), 0),
  SParamDB(PARAM(PB_CameraMatrix_I, ECGP_Matr_PB_Camera_I), 0),
  SParamDB(PARAM(PB_CameraMatrix_T, ECGP_Matr_PB_Camera_T), 0),  
  SParamDB(PARAM(PB_CameraMatrix, ECGP_Matr_PB_Camera), 0),
      
  SParamDB(PARAM(PI_Composite, ECGP_Matr_PI_Composite), 0),
  SParamDB(PARAM(PB_UnProjMatrix, ECGP_Matr_PB_UnProjMatrix), 0),
  SParamDB(PARAM(PB_ProjMatrix, ECGP_Matr_PB_ProjMatrix), 0),
  SParamDB(PARAM(PB_TerrainBaseMatrix, ECGP_Matr_PB_TerrainBase), 0),
  SParamDB(PARAM(PB_TerrainLayerGen, ECGP_Matr_PB_TerrainLayerGen), 0),
  SParamDB(PARAM(PB_VoxTerrainAtlasInfo, ECGP_Matr_PB_VoxTerrainAtlasInfo), 0),
  SParamDB(PARAM(PI_TransObjMatrix, ECGP_Matr_PI_Obj_T), 0), // Due to some bug in Parser, ObjMatrix_T or something

	SParamDB(PARAM(PB_TerrainLayerSlope, ECGP_PB_TerrainLayerSlope), 0),
  
  SParamDB(PARAM(PB_AmbientOpacity, ECGP_PB_AmbientOpacity), 0),

  SParamDB(PARAM(PI_MotionBlurData, ECGP_PI_MotionBlurData), 0),  
//	SParamDB(PARAM(PB_MotionBlurFrameData, ECGP_PB_MotionBlurFrameData), 0),  
	
  SParamDB(PARAM(PI_CloakParams, ECGP_PI_CloakParams), 0),
  SParamDB(PARAM(PI_TessParams, ECGP_PI_TessParams), 0),
   
  SParamDB(PARAM(PB_LightMatrix, ECGP_Matr_PB_LightMatrix), 0),
  SParamDB(PARAM(PB_TempMatr0, ECGP_Matr_PB_Temp4_0), PD_INDEXED),
  SParamDB(PARAM(PB_TempMatr1, ECGP_Matr_PB_Temp4_1), PD_INDEXED),
  SParamDB(PARAM(PB_TempMatr2, ECGP_Matr_PB_Temp4_2), PD_INDEXED),
  SParamDB(PARAM(PB_TempMatr3, ECGP_Matr_PB_Temp4_3), PD_INDEXED),
  SParamDB(PARAM(PI_TexMatrix, ECGP_Matr_PI_TexMatrix), 0, sParseTexMatrix),
  SParamDB(PARAM(PI_TCMMatrix, ECGP_Matr_PI_TCMMatrix), PD_INDEXED),
  SParamDB(PARAM(PI_TCGMatrix, ECGP_Matr_PI_TCGMatrix), PD_INDEXED),

  SParamDB(PARAM(PB_RotGridScreenOff, ECGP_PB_RotGridScreenOff), 0),
  SParamDB(PARAM(PB_DiffuseMulti, ECGP_PB_DiffuseMulti), 0),
  SParamDB(PARAM(PB_SpecularMulti, ECGP_PB_SpecularMulti), 0),

  SParamDB(PARAM(PL_LDiffuseColors, ECGP_PL_LDiffuseColors), 0),
  SParamDB(PARAM(PL_LSpecularColors, ECGP_PL_LSpecularColors), 0),
  SParamDB(PARAM(PL_LightsPos, ECGP_PL_LightsPos), 0),
  SParamDB(PARAM(PL_ShadowMasks, ECGP_PL_ShadowMasks), 0),
  SParamDB(PARAM(PL_LightsNum, ECGP_PL_LightsNum), 0),

  SParamDB(PARAM(PM_MatDiffuseColor, ECGP_PM_MatDiffuseColor), 0),
  SParamDB(PARAM(PM_MatSpecularColor, ECGP_PM_MatSpecularColor), 0),
  SParamDB(PARAM(PM_MatEmissiveColor, ECGP_PM_MatEmissiveColor), 0),
  
  SParamDB(PARAM(PI_OSCameraPos, ECGP_PI_OSCameraPos), 0),
	SParamDB(PARAM(PB_OutdoorAOParams, ECGP_PB_OutdoorAOParams), 0),
  SParamDB(PARAM(PI_Ambient, ECGP_PI_Ambient), 0),
  SParamDB(PARAM(PB_GlowParams, ECGP_PB_GlowParams), 0),
	SParamDB(PARAM(PB_StereoParams, ECGP_PB_StereoParams), 0),
  SParamDB(PARAM(PB_FurParams, ECGP_PB_FurParams), 0),
  SParamDB(PARAM(PB_ResourcesOpacity, ECGP_PB_ResourcesOpacity), 0),
  SParamDB(PARAM(PB_DetailParams, ECGP_PB_DetailParams), 0),
  SParamDB(PARAM(PI_VisionParams, ECGP_PI_VisionParams), 0),
	SParamDB(PARAM(PB_VisionMtlParams, ECGP_PB_VisionMtlParams), 0),
	SParamDB(PARAM(PI_EffectLayerParams, ECGP_PI_EffectLayerParams), 0),	
  SParamDB(PARAM(PB_RandomParams, ECGP_PB_RandomParams), 0),
  
  SParamDB(PARAM(PB_IrregKernel, ECGP_PB_IrregKernel), 0),
  SParamDB(PARAM(PB_RegularKernel, ECGP_PB_RegularKernel), 0),
  
	SParamDB(PARAM(PB_DeformWaveX, ECGP_PB_DeformWaveX), 0),
	SParamDB(PARAM(PB_DeformWaveY, ECGP_PB_DeformWaveY), 0),
	SParamDB(PARAM(PB_DeformFrequencies, ECGP_PB_DeformFrequencies), 0),
	SParamDB(PARAM(PB_DeformAmplitudes, ECGP_PB_DeformAmplitudes), 0),
	SParamDB(PARAM(PB_DeformLevels, ECGP_PB_DeformLevels), 0),
	SParamDB(PARAM(PB_DeformVertexPhases, ECGP_PB_DeformVertexPhases), 0),
	SParamDB(PARAM(PB_DeformBend, ECGP_PB_DeformBend), 0),
	SParamDB(PARAM(PB_DeformNoiseInfo, ECGP_PB_DeformNoiseInfo), 0),

  SParamDB(PARAM(PB_TFactor, ECGP_PB_TFactor), 0),
  SParamDB(PARAM(PI_AlphaTest, ECGP_PI_AlphaTest), 0),
  SParamDB(PARAM(PB_AlphaTest, ECGP_PB_AlphaTest), 0),
  SParamDB(PARAM(PI_MaterialLayersParams, ECGP_PI_MaterialLayersParams), 0),
  SParamDB(PARAM(PI_FrozenLayerParams, ECGP_PI_FrozenLayerParams), 0),  
  SParamDB(PARAM(PI_SnowVolumeParams, ECGP_PI_SnowVolumeParams), 0),
  SParamDB(PARAM(PB_TempData, ECGP_PB_TempData), PD_INDEXED | 0),
  SParamDB(PARAM(PB_DecalZFightingRemedy, ECGP_PB_DecalZFightingRemedy), 0),
  SParamDB(PARAM(PB_CameraFront, ECGP_PB_CameraFront), 0),  
  SParamDB(PARAM(PB_CameraRight, ECGP_PB_CameraRight), 0),
  SParamDB(PARAM(PB_CameraUp, ECGP_PB_CameraUp), 0),
  SParamDB(PARAM(PB_RTRect, ECGP_PB_RTRect), 0),
  SParamDB(PARAM(PB_VolumetricFogParams, ECGP_PB_VolumetricFogParams), 0),
  SParamDB(PARAM(PB_VolumetricFogRampParams, ECGP_PB_VolumetricFogRampParams), 0),
  SParamDB(PARAM(PB_VolumetricFogSunDir, ECGP_PB_VolumetricFogSunDir), 0),
  SParamDB(PARAM(PB_FogColGradColBase, ECGP_PB_FogColGradColBase), 0),
  SParamDB(PARAM(PB_FogColGradColDelta, ECGP_PB_FogColGradColDelta), 0),
  SParamDB(PARAM(PB_FogColGradParams, ECGP_PB_FogColGradParams), 0),
  SParamDB(PARAM(PB_FogColGradRadial, ECGP_PB_FogColGradRadial), 0),
  SParamDB(PARAM(PI_AvgFogVolumeContrib, ECGP_PI_AvgFogVolumeContrib), 0),  
  SParamDB(PARAM(PI_NumInstructions, ECGP_PI_NumInstructions), PD_INDEXED),
  SParamDB(PARAM(PI_ObjColor, ECGP_PI_ObjColor), 0),  
  SParamDB(PARAM(PB_LightningPos, ECGP_PB_LightningPos), 0),  
  SParamDB(PARAM(PB_LightningColSize, ECGP_PB_LightningColSize), 0),
  SParamDB(PARAM(PB_FromRE, ECGP_PB_FromRE), PD_INDEXED | 0),
  SParamDB(PARAM(PB_GlobalShaderFlag, ECGP_PB_GlobalShaderFlag), 0, sParseGlobalShaderFlag),
  SParamDB(PARAM(PB_RuntimeShaderFlag, ECGP_PB_RuntimeShaderFlag), 0, sParseRuntimeShaderFlag),
	SParamDB(PARAM(PB_ObjVal, ECGP_PB_ObjVal), PD_INDEXED),
  SParamDB(PARAM(PB_LightsNum, ECGP_PB_LightsNum), 0),
  SParamDB(PARAM(PB_WaterLevel, ECGP_PB_WaterLevel), 0),
  SParamDB(PARAM(PI_Wind, ECGP_PI_Wind), 0),
  SParamDB(PARAM(PI_TextureTileSize, ECGP_PI_TextureTileSize), 0),
	SParamDB(PARAM(PI_MotionBlurInfo, ECGP_PI_MotionBlurInfo), 0),
	SParamDB(PARAM(PI_ParticleParams, ECGP_PI_ParticleParams), 0),
  SParamDB(PARAM(PB_HDRDynamicMultiplier, ECGP_PB_HDRDynamicMultiplier), 0),
  SParamDB(PARAM(PB_CausticsParams, ECGP_PB_CausticsParams), 0),    
  SParamDB(PARAM(PB_CausticsSmoothSunDirection, ECGP_PB_CausticsSmoothSunDirection), 0),    
  SParamDB(PARAM(PF_SunDirection, ECGP_PF_SunDirection), 0),    
  SParamDB(PARAM(PF_FogColor, ECGP_PF_FogColor), 0),
  SParamDB(PARAM(PF_SunColor, ECGP_PF_SunColor), 0),
  SParamDB(PARAM(PB_SunColor, ECGP_PF_SunColor), 0),
	SParamDB(PARAM(PF_SkyColor, ECGP_PF_SkyColor), 0),
  SParamDB(PARAM(PF_Time, ECGP_PF_Time), 0, sParseTimeExpr),
  SParamDB(PARAM(PB_Time, ECGP_PF_Time), 0, sParseTimeExpr),
	SParamDB(PARAM(PF_FrameTime, ECGP_PF_FrameTime), 0, sParseTimeExpr),
	SParamDB(PARAM(PB_FrameTime, ECGP_PF_FrameTime), 0, sParseTimeExpr),
  SParamDB(PARAM(PF_ScreenSize, ECGP_PF_ScreenSize), 0),
  SParamDB(PARAM(PB_ScreenSize, ECGP_PF_ScreenSize), 0),
  SParamDB(PARAM(PF_CameraPos, ECGP_PF_CameraPos), 0),
  SParamDB(PARAM(PB_CameraPos, ECGP_PF_CameraPos), 0),
  SParamDB(PARAM(PF_NearFarDist, ECGP_PF_NearFarDist), 0),
  SParamDB(PARAM(PB_NearFarDist, ECGP_PF_NearFarDist), 0),

  SParamDB(PARAM(PF_FrustumPlaneEquation, ECGP_PF_FrustumPlaneEquation), 0),
  SParamDB(PARAM(PF_ShadowLightPos, ECGP_PF_ShadowLightPos), 0),
  SParamDB(PARAM(PF_ShadowViewPos, ECGP_PF_ShadowViewPos), 0),
  SParamDB(PARAM(PF_TessInfo, ECGP_PF_TessInfo), 0),

  SParamDB(PARAM(PF_ProjRatio, ECGP_PF_ProjRatio), 0),
  SParamDB(PARAM(PF_NearestScaled, ECGP_PF_NearestScaled), 0),
  SParamDB(PARAM(PF_DepthFactor, ECGP_PF_DepthFactor), 0),

	SParamDB(PARAM(PB_SFCompMat, ECGP_Matr_PB_SFCompMat), 0),  
	SParamDB(PARAM(PB_SFTexGenMat0, ECGP_Matr_PB_SFTexGenMat0), 0),
	SParamDB(PARAM(PB_SFTexGenMat1, ECGP_Matr_PB_SFTexGenMat1), 0),
	SParamDB(PARAM(PB_SFBitmapColorTransform, ECGP_PB_SFBitmapColorTransform), 0),
	SParamDB(PARAM(PB_SFColorTransformMatrix, ECGP_PB_SFColorTransformMatrix), 0),
	SParamDB(PARAM(PB_SFStereoVideoFrameSelect, ECGP_PB_SFStereoVideoFrameSelect), 0),
	SParamDB(PARAM(PB_SFPremultipliedAlpha, ECGP_PB_SFPremultipliedAlpha), 0),
	SParamDB(PARAM(PB_SFBlurFilterSize, ECGP_PB_SFBlurFilterSize), 0),
	SParamDB(PARAM(PB_SFBlurFilterScale, ECGP_PB_SFBlurFilterScale), 0),
	SParamDB(PARAM(PB_SFBlurFilterOffset, ECGP_PB_SFBlurFilterOffset), 0),
	SParamDB(PARAM(PB_SFBlurFilterColor1, ECGP_PB_SFBlurFilterColor1), 0),
	SParamDB(PARAM(PB_SFBlurFilterColor2, ECGP_PB_SFBlurFilterColor2), 0),

	SParamDB(PARAM(PI_OceanMat, ECGP_Matr_PI_OceanMat), 0),

	SParamDB(PARAM(PI_HMAGradients, ECGP_PI_HMAGradients), 0),

	SParamDB(PARAM(PB_CloudShadingColorSun, ECGP_PB_CloudShadingColorSun), 0),
	SParamDB(PARAM(PB_CloudShadingColorSky, ECGP_PB_CloudShadingColorSky), 0),

	SParamDB(PARAM(PB_ResInfoDiffuse, ECGP_PB_ResInfoDiffuse), 0),
	SParamDB(PARAM(PB_ResInfoBump, ECGP_PB_ResInfoBump), 0),
	SParamDB(PARAM(PB_TexelDensityParam, ECGP_PB_TexelDensityParam), 0),
	SParamDB(PARAM(PB_TexelDensityColor, ECGP_PB_TexelDensityColor), 0),
	SParamDB(PARAM(PB_TexelsPerMeterInfo, ECGP_PB_TexelsPerMeterInfo), 0),

  SParamDB(PARAM(SG_FrustrumInfo, ECGP_SG_FrustrumInfo), 0),

  SParamDB(PARAM(SG_ShadowMatr0, ECGP_Matr_SG_ShadowProj_0), 0),
  SParamDB(PARAM(SG_ShadowMatr1, ECGP_Matr_SG_ShadowProj_1), 0),
  SParamDB(PARAM(SG_ShadowMatr2, ECGP_Matr_SG_ShadowProj_2), 0),
  SParamDB(PARAM(SG_ShadowMatr3, ECGP_Matr_SG_ShadowProj_3), 0),

	SParamDB(PARAM(PB_GIGridMatrix, ECGP_Matr_PB_GIGridMatrix), 0),
	SParamDB(PARAM(PB_GIInvGridMatrix, ECGP_Matr_PB_GIInvGridMatrix), 0),
	SParamDB(PARAM(PB_GIGridSize, ECGP_PB_GIGridSize), 0),
	SParamDB(PARAM(PB_GIInvGridSize, ECGP_PB_GIInvGridSize), 0),
	SParamDB(PARAM(PB_GIGridSpaceCamPos, ECGP_PB_GIGridSpaceCamPos), 0),
	SParamDB(PARAM(PB_GIAttenuation, ECGP_PB_GIAttenuation), 0),
	SParamDB(PARAM(PB_GIGridCenter, ECGP_PB_GIGridCenter), 0),

	SParamDB()
};

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

const char *CShaderMan::mfGetShaderParamName(ECGParam ePR)
{
  int n = 0;
  const char *szName;
  while (szName=sParams[n].szName)
  {
    if (sParams[n].eParamType == ePR)
      return szName;
    n++;
  }
  if (ePR == ECGP_PM_Tweakable)
    return "PM_Tweakable";
  return NULL;
}

SParamDB *CShaderMan::mfGetShaderParamDB(const char *szSemantic)
{
  const char *szName;
  int n = 0;
  while (szName=sParams[n].szName)
  {
    int nLen = strlen(szName);
    if (!strnicmp(szName, szSemantic, nLen) || (sParams[n].szAliasName && !strnicmp(sParams[n].szAliasName, szSemantic, strlen(sParams[n].szAliasName))))
      return &sParams[n];
    n++;
  }
  return NULL;
}

bool CShaderMan::mfParseParamComp(int comp, SCGParam *pCurParam, const char *szSemantic, char *params, const char *szAnnotations, SShaderFXParams& FXParams, CShader *ef, uint32 nParamFlags, EHWShaderClass eSHClass, bool bExpressionOperand)
{
  if (comp >= 4 || comp < -1)
    return false;
  if (!pCurParam)
    return false;
  if (comp > 0)
    pCurParam->m_Flags &= ~PF_SINGLE_COMP;
  else
    pCurParam->m_Flags |= PF_SINGLE_COMP;
  if (!szSemantic || !szSemantic[0])
  {
    if (!pCurParam->m_pData)
      pCurParam->m_pData = new SParamData;
    pCurParam->m_pData->d.fData[comp] = shGetFloat(params);
    if (!((nParamFlags>>comp) & PF_TWEAKABLE_0))
      pCurParam->m_eCGParamType = (ECGParam)((int)pCurParam->m_eCGParamType | (int)(ECGP_PB_Scalar << (comp*8)));
    else
    {
      pCurParam->m_eCGParamType = (ECGParam)((int)pCurParam->m_eCGParamType | (int)(ECGP_PM_Tweakable << (comp*8)));
      if (!bExpressionOperand)
      {
        pCurParam->m_eCGParamType = (ECGParam)((int)pCurParam->m_eCGParamType | (int)ECGP_PM_Tweakable);
        pCurParam->m_Flags |= PF_MATERIAL | PF_SINGLE_COMP;
      }
    }
    return true;
  }
  if (!stricmp(szSemantic, "NULL"))
    return true;
  if (szSemantic[0] == '(')
  {
    pCurParam->m_eCGParamType = ECGP_PM_Tweakable;
    pCurParam->m_Flags |= PF_SINGLE_COMP | PF_MATERIAL;
    return true;
  }
  const char *szName;
  int n = 0;
  while (szName=sParams[n].szName)
  {
    int nLen = strlen(szName);
    if (!strnicmp(szName, szSemantic, nLen) || (sParams[n].szAliasName && !strnicmp(sParams[n].szAliasName, szSemantic, strlen(sParams[n].szAliasName))))
    {
      if (sParams[n].nFlags & PD_MERGED)
        pCurParam->m_Flags |= PF_CANMERGED;
      if (!strnicmp(szName, "PI_", 3))
        pCurParam->m_Flags |= PF_INSTANCE;
      else
      if (!strnicmp(szName, "SI_", 3))
        pCurParam->m_Flags |= PF_INSTANCE;
      else
      if (!strnicmp(szName, "PF_", 3))
        pCurParam->m_Flags |= PF_GLOBAL;
      else
      if (!strnicmp(szName, "PM_", 3))
        pCurParam->m_Flags |= PF_MATERIAL;
      else
      if (!strnicmp(szName, "PL_", 3))
        pCurParam->m_Flags |= PF_LIGHT;
      else
      if (!strnicmp(szName, "SG_", 3))
        pCurParam->m_Flags |= PF_SHADOWGEN;
      assert(sParams[n].eParamType < 256);
      if (comp > 0)
        pCurParam->m_eCGParamType = (ECGParam)((int)pCurParam->m_eCGParamType | (int)(sParams[n].eParamType << (comp*8)));
      else
        pCurParam->m_eCGParamType = sParams[n].eParamType;
      if (pCurParam->m_nParameters > 1)
        pCurParam->m_Flags |= PF_MATRIX;
      if (sParams[n].nFlags & PD_INDEXED)
      {
        if (szSemantic[nLen] == '[')
        {
          int nID = shGetInt(&szSemantic[nLen+1]);
          assert(nID < 256);
          if (comp > 0)
            nID <<= (comp*8);
          pCurParam->m_nID |= nID;
        }
      }
      if (sParams[n].ParserFunc)
        sParams[n].ParserFunc(params ? params : szSemantic, szAnnotations, &FXParams.m_FXSamplers, pCurParam, comp, ef);
      break;
    }
    n++;
  }
  if (!szName)
    return false;
  return true;
}

bool CShaderMan::mfParseCGParam(char *scr, const char *szAnnotations, SShaderFXParams& FXParams, CShader *ef, std::vector<SCGParam>* pParams, int nComps, uint32 nParamFlags, EHWShaderClass eSHClass, bool bExpressionOperand)
{
  char* name;
  long cmd;
  char *params;
  char *data;

  int nComp = 0;

  enum {eComp=1, eParam, eName};
  static STokenDesc commands[] =
  {
    {eName, "Name"},
    {eComp, "Comp"},
    {eParam, "Param"},
    {0,0}
  };
  SCGParam vpp;
  int n = pParams->size();
  bool bRes = true;

  while ((cmd = shGetObject (&scr, commands, &name, &params)) > 0)
  {
    data = NULL;
    if (name)
      data = name;
    else
    if (params)
      data = params;

    switch (cmd)
    {
      case eName:
        vpp.m_Name = data;
        break;
      case eComp:
        {
          if (nComp < 4)
          {
            bRes &= mfParseParamComp(nComp, &vpp, name, params, szAnnotations, FXParams, ef, nParamFlags, eSHClass, bExpressionOperand);
            nComp++;
          }
        }
        break;
      case eParam:
        if (!name)
          name = params;
        bRes &= mfParseParamComp(-1, &vpp, name, params, szAnnotations, FXParams, ef, nParamFlags, eSHClass, bExpressionOperand);
        break;
    }
  }
  if (n == pParams->size())
    pParams->push_back(vpp);
  assert(bRes == true);
  return bRes;
}

bool CShaderMan::mfParseFXParameter(SShaderFXParams& FXParams, SFXParam *pr, const char *ParamName, CShader *ef, bool bInstParam, int nParams, std::vector<SCGParam>* pParams, EHWShaderClass eSHClass, bool bExpressionOperand)
{
  SCGParam CGpr;
  char scr[256];

  uint32 nParamFlags = pr->GetParamFlags();

  CryFixedStringT<512> Semantic = "Name=";
  Semantic += ParamName;
  Semantic += " ";
  int nComps = 0;
  if (!pr->m_Assign.empty())
  {
    Semantic += "Param=";
    Semantic += pr->m_Assign.c_str();
    nComps = pr->m_nComps;
  }
  else
  {
    for (int i=0; i<pr->m_nComps; i++)
    {
      if (i)
        Semantic += " ";
      string cur = pr->GetParamComp(i);
      if (!cur[0])
        break;
      nComps++;
      if ((cur[0] == '-' && isdigit(uint8(cur[1]))) || isdigit(uint8(cur[0])))
        sprintf(scr, "Comp = %s", cur.c_str());
      else
        sprintf(scr, "Comp '%s'", cur.c_str());
      Semantic += scr;
    }
  }
  // Process parameters only with semantics
  if (nComps)
  {
    uint32 nOffs = pParams->size();
    bool bRes = mfParseCGParam((char *)Semantic.c_str(), pr->m_Annotations.c_str(), FXParams, ef, pParams, nComps, nParamFlags, eSHClass, bExpressionOperand);
    assert(bRes);
    if (pParams->size() > nOffs)
    {
      //assert(pBind->m_nComponents == 1);
      SCGParam &p = (*pParams)[nOffs];
      p.m_dwBind = -1;
      p.m_nParameters = nParams;
      p.m_Flags |= nParamFlags;
      if (p.m_Flags & PF_AUTOMERGED)
      {
        if (!p.m_pData)
          p.m_pData = new SParamData;
        const char *src = p.m_Name.c_str();
        for (uint32 i=0; i<4; i++)
        {
          char param[128];
          char dig = i + 0x30;
          while (*src)
          {
            if (src[0] == '_' && src[1] == '_' && src[2] == dig)
            {
              int n = 0;
              src += 3;
              while (src[n])
              {
                if (src[n] == '_' && src[n+1] == '_')
                  break;
                param[n] = src[n];
                n++;
              }
              param[n] = 0;
              src += n;
              if (param[0])
                p.m_pData->m_CompNames[i] = param;
              break;
            }
            else
              src++;
          }
        }
      }
    }
    return bRes;
  }
  // Parameter without semantic
  return false;
}

//===========================================================================================

bool SShaderParam::GetValue(const char* szName, DynArrayRef<SShaderParam> *Params, float *v, int nID)
{
  int i;
  bool bRes = false;
  for (i=0; i<Params->size(); i++)
  {
    SShaderParam *sp = &(*Params)[i];

    if (!sp)
      continue;
    if (!stricmp(sp->m_Name, szName))
    {
      bRes = true;
      switch (sp->m_Type)
      {
      case eType_HALF:
      case eType_FLOAT:
        v[nID] = sp->m_Value.m_Float;
        break;
      case eType_SHORT:
        v[nID] = (float)sp->m_Value.m_Short;
        break;
      case eType_INT:
      case eType_TEXTURE_HANDLE:
        v[nID] = (float)sp->m_Value.m_Int;
        break;

      case eType_VECTOR:
        v[0] = sp->m_Value.m_Vector[0];
        v[1] = sp->m_Value.m_Vector[1];
        v[2] = sp->m_Value.m_Vector[2];
        break;

      case eType_FCOLOR:
        v[0] = sp->m_Value.m_Color[0];
        v[1] = sp->m_Value.m_Color[1];
        v[2] = sp->m_Value.m_Color[2];
        v[3] = sp->m_Value.m_Color[3];
        break;

      case eType_STRING:
        assert(0);
        bRes = false;
        break;
      case eType_UNKNOWN:
        assert(0);
        bRes = false;
        break;
      }
      break;
    }
  }
  return bRes;
}

bool sGetPublic(const CCryNameR& n, float *v, int nID)
{
  CRenderer *rd = gRenDev;
  bool bFound = false;
  SRenderShaderResources *pRS;
  const char *cName = n.c_str();
  if (pRS = rd->m_RP.m_pShaderResources)
    bFound = SShaderParam::GetValue(cName, &pRS->m_ShaderParams, v, nID);
  if (!bFound && rd->m_RP.m_pShader)
  {
    DynArray<SShaderParam>& PublicParams = rd->m_cEF.m_Bin.mfGetFXParams(rd->m_RP.m_pShader).m_PublicParams;
    bFound = SShaderParam::GetValue(cName, &PublicParams, v, nID);
  }
  return bFound;
}

SParamData::~SParamData()
{
}

SParamData::SParamData(const SParamData& sp)
{
  for (int i=0; i<4; i++)
  {
    m_CompNames[i] = sp.m_CompNames[i];
    d.nData64[i] = sp.d.nData64[i];
  }
}
